package com.jsbs.iam.user.service.impl;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.jsbs.iam.common.core.constant.EmployeeConstants;
import com.jsbs.iam.common.core.dto.Result;
import com.jsbs.iam.common.core.param.AccountInfoDto;
import com.jsbs.iam.common.core.utils.Json;
import com.jsbs.iam.common.core.utils.PageHelperTool;
import com.jsbs.iam.common.core.utils.StringUtils;
import com.jsbs.iam.common.core.utils.bean.BeanUtils;
import com.jsbs.iam.common.redis.service.RedisUtils;
import com.jsbs.iam.user.constant.Constants;
import com.jsbs.iam.user.constant.RedisConstants;
import com.jsbs.iam.user.dto.*;
import com.jsbs.iam.user.entity.*;
import com.jsbs.iam.user.feign.ApplySystemFeign;
import com.jsbs.iam.user.feign.IdentFeignInterface;
import com.jsbs.iam.user.mapper.*;
import com.jsbs.iam.user.param.*;
import com.jsbs.iam.user.service.OrgInfoService;
import com.jsbs.iam.user.service.UserInfoService;
import com.jsbs.iam.user.vo.*;
import io.netty.util.internal.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

@Service
@Slf4j
public class UserInfoServiceImpl implements UserInfoService {

    @Autowired
    private UserInfoMapper userInfoMapper;

    @Autowired
    private UserSyncErrorLogMapper userSyncErrorLogMapper;

    @Autowired
    private AccountServiceImpl accountService;

    @Resource
    private RedissonClient redissonClient;

    @Autowired
    private OrgInfoService orgInfoService;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private IdentFeignInterface identFeignInterface;

    @Autowired
    private ApplySystemFeign applySystemFeign;

    @Autowired
    private UserTypeMapper userTypeMapper;

    @Autowired
    private OrgInfoMapper orgInfoMapper;

    @Autowired
    private AdminRoleMapper adminRoleMapper;

    @Value("${_env.name}")
    private String envName;

    @Override
    public List<UserInfoResp> syncUserInfo(UserInfoParam userInfoParam) {
        // 集合判空
        if (CollectionUtils.isEmpty(userInfoParam.getUserInfoList())) {
            return new ArrayList<>();
        }
        // 异常用户信息
        List<UserSyncErrorLog> errorLogs = new ArrayList<>();
        // 校验通过用户信息
        List<UserInfoDto> userInfoDtoList = new ArrayList<>();
        // 生效用户
        List<UserInfoDto> enableUserInfo = userInfoParam.getUserInfoList().stream().filter(item -> item.getStatus() == 1).collect(Collectors.toList());
        // 去除重复手机号数据
        List<UserInfoDto> distinctEnableUserInfo = enableUserInfo.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(UserInfoDto::getPhone))), ArrayList::new));
        // 校验失败返回失败用户信息，校验生效用户
        List<UserInfoResp> respList = checkForUserInfo(userInfoParam.getCompanyCode(), userInfoParam.getDataSource(), distinctEnableUserInfo, userInfoDtoList, errorLogs);
        // 失效用户+校验通过用户
        userInfoDtoList.addAll(userInfoParam.getUserInfoList().stream().filter(item -> item.getStatus() == 0).collect(Collectors.toList()));
        // 转换后的用户信息
        List<UserInfoParams> userInfoParamsList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(userInfoDtoList)) {
            // 根据用户类型获取对应的扩展字段信息
            List<IamUserTypeExtendedFieldVo> fieldList = userTypeMapper.queryByUserTypeCode(userInfoParam.getUserTypeCode());
            userInfoDtoList.forEach(item -> {
                // 性别字典值转换
                item.setGender(String.valueOf(EmployeeConstants.employeeMap.get(item.getGender())));
                // 民族转换
                item.setNation((String) EmployeeConstants.employeeMap.get(item.getNation()));
                // 员工状态转换
                item.setEmployeeStatus(String.valueOf(EmployeeConstants.employeeMap.get(item.getEmployeeStatus())));
                // 工作性质
                item.setJobType(String.valueOf(EmployeeConstants.employeeMap.get(item.getJobType())));
                // 是否异常人员
                item.setIsExceEmpl(String.valueOf(EmployeeConstants.employeeMap.get(item.getIsExceEmpl())));
                // 是否管培生
                item.setIsTrainEmpl(String.valueOf(EmployeeConstants.employeeMap.get(item.getIsTrainEmpl())));
                UserInfoParams userInfoParams = new UserInfoParams();
                BeanUtils.copyProperties(item, userInfoParams);
                userInfoParams.setDataSource(userInfoParam.getDataSource());
                userInfoParams.setCompanyCode(userInfoParam.getCompanyCode());
                userInfoParams.setUserTypeCode(userInfoParam.getUserTypeCode());
                List<Map<String, Object>> extendFieldList = new ArrayList<>();
                // 封装扩展字段
                if (CollectionUtils.isNotEmpty(fieldList)) {
                    // 字段转成map集合
                    Map<String, Object> itemMap = convernetIntoMapValue(item);
                    fieldList.forEach(info -> {
                        Map<String, Object> extendFieldMap = new HashMap<>();
                        // 值不为空
                        if (StringUtils.isNotEmpty(MapUtils.getString(itemMap, info.getFieldName()))) {
                            // 扩展字段，fieldKey:字段名
                            extendFieldMap.put(Constants.FIELD_KEY, info.getFieldName());
                            // 扩展字段 fieldValue:字段值
                            extendFieldMap.put(Constants.FIELD_VALUE, MapUtils.getString(itemMap, info.getFieldName()));
                            // 扩展字段 fieldId:
                            extendFieldMap.put(Constants.FIELD_ID, info.getFieldId());
                        }
                        // 扩展字段值不为空，封装成map
                        if (MapUtils.isNotEmpty(extendFieldMap)) {
                            extendFieldList.add(extendFieldMap);
                        }
                    });
                }
                // 扩展字段不为空
                if (CollectionUtils.isNotEmpty(extendFieldList)) {
                    userInfoParams.setExtendFieldList(extendFieldList);
                }
                // 用户信息中间状态数据集合
                userInfoParamsList.add(userInfoParams);
            });
        }
        // 批量入异常表
        if (CollectionUtils.isNotEmpty(errorLogs)) {
            userSyncErrorLogMapper.batchInser(errorLogs);
        }
        // 处理转换后的用户信息
        dealForUserInfo(userInfoParamsList);
        return respList;
    }

    /**
     * 功能描述：将实体类转成map
     * @param userInfoDto
     * @return
     */
    private static Map<String, Object> convernetIntoMapValue(UserInfoDto userInfoDto){
        Map<String, Object> result = new HashMap<>();
        try {
            Field[] fields = userInfoDto.getClass().getDeclaredFields();
            String separator = "_";
            for (Field field : fields) {
                String name = field.getName();
                name = name.substring(0, 1).toUpperCase() + name.substring(1); // 将属性的首字符大写，方便构造get，set方法
                Method m = userInfoDto.getClass().getMethod("get" + name);
                // 转成下划线
                //result.put(field.getName().replaceAll("([a-z])([A-Z])", "$1"+separator+"$2").toLowerCase(), m.invoke(userInfoDto));
                // 驼峰
                result.put(field.getName(), m.invoke(userInfoDto));
            }
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return result;
    }

    @Override
    public void dealForUserInfo(List<UserInfoParams> userInfoParamsList) {
        // 集合判空
        if (CollectionUtils.isEmpty(userInfoParamsList)) {
            return;
        }
        // 循环处理用户信息
        if (CollectionUtils.isNotEmpty(userInfoParamsList)) {
            userInfoParamsList.forEach(item -> {
                // 判断当前用户是否存在
                String userCode = userInfoMapper.queryUserCode(item.getCompanyCode(), item.getDataSource(), item.getPhone());
                if (StringUtils.isNotEmpty(userCode)) {
                    item.setUserCode(userCode);
                }
            });
        }
        // 新增用户
        List<UserInfoParams> userInfoList = userInfoParamsList.stream().filter(item -> StringUtils.isEmpty(item.getUserCode())).collect(Collectors.toList());
        // 批量新增用户
        if (CollectionUtils.isNotEmpty(userInfoList)) {
            // 新增用户生成用户ID时加锁，失效时间10分钟
            RLock lock = redissonClient.getLock(RedisConstants.USER_INFO_CODE_LOCK);
            Long code = null;
            try {
                // 5分钟内重试获取锁，10秒后释放
                boolean isLocked = lock.tryLock(5 * 60 * 1000L, 10 * 1000L, TimeUnit.MILLISECONDS);
                // 获取到锁后，进行自增
                if (!isLocked) {
                    log.warn("Route=>UserInfoServiceImpl method=>syncUserInfo 同步人资用户信息加锁生成用户ID失败:{}", Json.toJsonString(userInfoParamsList));
                    throw new Exception();
                }
                // 加锁成功后获取当前缓存值
                String value = RedisUtils.get(envName + RedisConstants.USER_INFO_CODE);
                // 若为空则从数据库取当前最大值，并加新增用户数量入缓存
                if (StringUtils.isEmpty(value)) {
                    code = Long.valueOf(userInfoMapper.getMaxUserCode()) + 1;
                } else {
                    // 当前缓存获取成功，并加新增用户数量入缓存
                    code = Long.parseLong(value) + 1;
                }
                // 将最新值更新到缓存中
                RedisUtils.set(envName + RedisConstants.USER_INFO_CODE, String.valueOf(code + userInfoList.size() - 1));
            } catch (Exception e) {
                log.error("Route=>UserInfoServiceImpl method=>syncUserInfo 同步人资用户信息加锁生成用户ID失败:{}, e:{}", Json.toJsonString(userInfoParamsList), e);
                throw new RuntimeException("同步用户信息生成用户ID异常");
            } finally {
                // 手动解锁
                if (lock.isLocked()) {
                    lock.unlock();
                }
            }
            AtomicReference<Long> finalCode = new AtomicReference<>(code);
            // 新增用户信息
            List<IamUserInfo> userInfos = new ArrayList<>();
            userInfoList.forEach(item -> {
                IamUserInfo userInfo = new IamUserInfo();
                BeanUtils.copyProperties(item, userInfo);
                userInfo.setOrgTypeCode(item.getDataSource());
                // 默认同步
                userInfo.setSyncFlag(0);
                // 用户ID每次+1
                userInfo.setUserCode(String.format("%010d", finalCode.getAndSet(finalCode.get() + 1)));
                item.setUserCode(userInfo.getUserCode());
                userInfo.setCreatePerson("人资同步");
                userInfo.setUpdatePerson("人资同步");
                userInfos.add(userInfo);
            });
            if (CollectionUtils.isNotEmpty(userInfos)) {
                // 批量新增用户信息
                userInfoMapper.batchInsert(userInfos);
                // 新增用户自动创建账户
                accountService.autoCreateAccount(userInfos);
            }
        }
        // 更新用户
        List<UserInfoParams> updateList = userInfoParamsList.stream().filter(item -> StringUtils.isNotEmpty(item.getUserCode())).collect(Collectors.toList());
        // 批量更新用户
        if (CollectionUtils.isNotEmpty(updateList)) {
            // 更新的用户信息
            List<IamUserInfo> userInfos = new ArrayList<>();
            updateList.forEach(item -> {
                IamUserInfo userInfo = new IamUserInfo();
                BeanUtils.copyProperties(item, userInfo);
                userInfo.setOrgTypeCode(item.getDataSource());
                userInfos.add(userInfo);
            });
            // 批量更新用户信息
            if (CollectionUtils.isNotEmpty(userInfos)) {
                userInfoMapper.batchUpdate(userInfos);
                // 将有效 -> 失效的用户对应的账号信息置为失效
                List<String> failUserCodeList = userInfos.stream().filter(item -> 0 == item.getStatus()).map(item -> item.getUserCode()).collect(Collectors.toList());
                if (CollectionUtils.isNotEmpty(failUserCodeList)) {
                    // 将失效用户对应的账户置为失效
                    identFeignInterface.autoFailUserAccount(failUserCodeList);
                }
            }
        }
        // 批量处理扩展字段
        userInfoParamsList.forEach(item -> {
            if (StringUtils.isNotEmpty(item.getUserCode())) {
                // 根据userCode先删除所有扩展字段
                userInfoMapper.deleteExtendedByUserCode(item.getUserCode());
            }
            // 无效用户不新增扩展字段
            if (0 == item.getStatus()) {
                return;
            }
            // 用户对应的扩展字段列表
            List<Map<String, Object>> extendFields = item.getExtendFieldList();
            if (CollectionUtils.isEmpty(extendFields)) {
                return;
            }
            List<IamUserTypeExtended> userTypeExtendeds = new ArrayList<>();
            extendFields.forEach(info -> {
                IamUserTypeExtended extended = new IamUserTypeExtended();
                extended.setCompanyCode(item.getCompanyCode());
                extended.setFieldId(MapUtils.getString(info, Constants.FIELD_ID));
                extended.setFieldData(MapUtils.getString(info, Constants.FIELD_VALUE));
                extended.setUserCode(item.getUserCode());
                extended.setCreatePerson("人资同步");
                extended.setUpdatePerson("人资同步");
                userTypeExtendeds.add(extended);
            });
            if (CollectionUtils.isEmpty(userTypeExtendeds)) {
                return;
            }
            // 批量新增
            userInfoMapper.batchInsertExtended(userTypeExtendeds);
        });
    }

    /**
     * 功能描述：用户信息校验
     * @param companyCode
     * @param dataSource
     * @param userInfoDtoList
     * @param infoDtoList
     * @param errorLogs
     * @return
     */
    private List<UserInfoResp> checkForUserInfo(String companyCode, String dataSource, List<UserInfoDto> userInfoDtoList, List<UserInfoDto> infoDtoList, List<UserSyncErrorLog> errorLogs){
        List<UserInfoResp> respList = new ArrayList<>();
        userInfoDtoList.forEach(item -> {
            // 异常标识
            boolean userFlag = false;
            // 异常信息
            String errorMsg = "";
            // 员工信息为空
            if (StringUtils.isEmpty(item.getEmpId())) {
                userFlag = true;
                errorMsg = "人员主键为空";
            }
            if (StringUtils.isEmpty(item.getEmployeeCode())) {
                userFlag = true;
                errorMsg = "员工编号为空";
            }
            if (StringUtils.isEmpty(item.getUserId())) {
                userFlag = true;
                errorMsg = "用户ID为空";
            }
            if (StringUtils.isEmpty(item.getPhone())) {
                userFlag = true;
                errorMsg = "手机号为空";
            }
            // 同一组织架构下、有效状态用户手机号唯一
            /*if (userInfoMapper.countForUser(companyCode, dataSource, item.getUserId(), item.getPhone(), null) > 0) {
                userFlag = true;
                errorMsg = "手机号重复";
            }*/

            // 同一组织架构下有效状态员工编号唯一
            /*if (userInfoMapper.countForUser(companyCode, dataSource, item.getUserId(), null, item.getEmployeeCode()) > 0) {
                userFlag = true;
                errorMsg = "员工编号重复";
            }*/
            // 归属组织集合
            List<String> orgCodeList = new ArrayList<>();
            if (StringUtils.isNotEmpty(item.getBusinessOrgCode()))
                orgCodeList.addAll(Arrays.asList(item.getBusinessOrgCode().split(",")));
            if (StringUtils.isNotEmpty(item.getPartitionOrgCode()))
                orgCodeList.addAll(Arrays.asList(item.getPartitionOrgCode().split(",")));
            if (StringUtils.isNotEmpty(item.getBusinessPostId()))
                orgCodeList.addAll(Arrays.asList(item.getBusinessPostId().split(",")));
            if (StringUtils.isNotEmpty(item.getPartitionPostId()))
                orgCodeList.addAll(Arrays.asList(item.getPartitionPostId().split(",")));
            if (StringUtils.isNotEmpty(item.getConcurrentPost()))
                orgCodeList.addAll(Arrays.asList(item.getConcurrentPost().split(",")));
            if (StringUtils.isNotEmpty(item.getConcurrentPostOrg()))
                orgCodeList.addAll(Arrays.asList(item.getConcurrentPostOrg().split(",")));
            // 去空
            orgCodeList.removeAll(Arrays.asList(StringUtils.EMPTY, null));
            if (CollectionUtils.isEmpty(orgCodeList)) {
                userFlag = true;
                errorMsg = "员工归属组织为空";
            } else {
                // 归属组织，逗号间隔
                item.setOrgCode(orgCodeList.stream().collect(Collectors.joining(",")));
            }
            // 用户信息异常
            if (userFlag) {
                UserInfoResp userInfoResp = new UserInfoResp();
                UserSyncErrorLog userSyncErrorLog = new UserSyncErrorLog();
                userInfoResp.setUserId(item.getUserId());
                userInfoResp.setEmpId(item.getEmpId());
                userInfoResp.setMsg(errorMsg);
                BeanUtils.copyProperties(item, userSyncErrorLog);
                userSyncErrorLog.setCompanyCode(companyCode);
                userSyncErrorLog.setErrorMsg(errorMsg);
                respList.add(userInfoResp);
                errorLogs.add(userSyncErrorLog);
                return;
            }
            infoDtoList.add(item);
        });
        return respList;
    }


    /**
     * 功能描述：根据用户编码（usercode工号）,开通账号
     * @param userCode
     * @return int
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean openAccount(List<String> userCode) {
        try{
            boolean openAccount = userInfoMapper.openAccount(userCode);
            if(openAccount){
                log.info("Route==>UserInfoServiceImpl method=openAccoun 用户开通账户成功！",JSON.toJSONString(userCode));
                return true;
            }
            return false;
        }catch(Exception e){
            throw new RuntimeException("用户中心开通账户异常！");
        }
    }

    @Override
    public List<String> getRoleCode(String userCode) {
        //根据用户id查询角色编码
        return userInfoMapper.getRoleCode(userCode);
    }

    /**
     * 功能描述：根据用户id（usercode）,批量将用户设置为未开通
     * @param userCode
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int batchDeleteByUserCode(List<String> userCode) {
        return userInfoMapper.batchDeleteByUserCode(userCode);
    }

    @Override
    public PageInfo<UserQueryResp> queryUserByParam(UserQueryParam userQueryParam) {
        userQueryParam.initPage();
        PageHelper.startPage(userQueryParam.getPageNum(),userQueryParam.getPageSize());
        // 查询用户列表数据
        List<IamUserInfo> userInfoList = userInfoMapper.queryUserByParam(userQueryParam);
        if (CollectionUtils.isEmpty(userInfoList)) {
            return new PageInfo<>();
        }
        // 返回结果集
        List<UserQueryResp> respList = new ArrayList<>();
        // 循环处理，封装数据
        userInfoList.forEach(item -> {
            UserQueryResp queryResp = new UserQueryResp();
            BeanUtils.copyProperties(item, queryResp);
            List<String> orgcodeList = Arrays.asList(item.getOrgCode().split(","));
            if (CollectionUtils.isNotEmpty(orgcodeList)) {
                // 根据组织类型+组织编码查询
                List<OrgInfoTypeVo> orgInfoVos = orgInfoService.queryByCode(orgcodeList, item.getOrgTypeCode());
                List<String> orgInfos = new ArrayList<>();
                // 封装组织数据
                if (CollectionUtils.isNotEmpty(orgInfoVos)) {
                    orgInfoVos.forEach(info -> {
                        orgInfos.add(info.getOrgTypeName() + "-" + info.getOrgName());
                    });
                    // 封账
                    queryResp.setOrgInfos(orgInfos);
                }
            }
            respList.add(queryResp);
        });
        PageInfo<UserQueryResp> pageInfo0= new PageInfo<>(respList);
        return pageInfo0;
    }

    /**
     * 功能描述：只查询未开通账户的用户
     * @param userQueryParam
     * @return PageInfo
     */
    @Override
    public PageInfo<UserQueryResp> queryUserNotOpen(UserQueryParam userQueryParam) {
        userQueryParam.initPage();
        PageHelper.startPage(userQueryParam.getPageNum(),userQueryParam.getPageSize());
        // 查询未开通账户的用户列表数据
        List<IamUserInfo> userInfoLists = userInfoMapper.queryUserNotOpen(userQueryParam);
        PageInfo<IamUserInfo> initPageInfo = new PageInfo<>(userInfoLists);
        if (CollectionUtils.isEmpty(userInfoLists)) {
            return new PageInfo<>();
        }
        // 返回结果集
        List<UserQueryResp> respList = new ArrayList<>();
        // 循环处理，封装数据
        initPageInfo.getList().forEach(item -> {
            UserQueryResp queryResp = new UserQueryResp();
            BeanUtils.copyProperties(item, queryResp);
            List<String> orgcodeList = Arrays.asList(item.getOrgCode().split(","));
            if (CollectionUtils.isNotEmpty(orgcodeList)) {
                // 根据组织类型+组织编码查询
                List<OrgInfoTypeVo> orgInfoVos = orgInfoService.queryByCode(orgcodeList, item.getOrgTypeCode());
                List<String> orgInfos = new ArrayList<>();
                // 封装组织数据
                if (CollectionUtils.isNotEmpty(orgInfoVos)) {
                    orgInfoVos.forEach(info -> {
                        orgInfos.add(info.getOrgTypeName() + "-" + info.getOrgName());
                    });
                    // 封账
                    queryResp.setOrgInfos(orgInfos);
                }
            }
            respList.add(queryResp);
        });
        PageInfo<UserQueryResp> pageInfo0= new PageInfo<>(respList);
        PageInfo<UserQueryResp> pageInfo = PageHelperTool.initPageInfoObj(userQueryParam.getPageNum(), (int) initPageInfo.getTotal(),
                userQueryParam.getPageSize(), pageInfo0);
        return pageInfo;
    }

    @Override
    public PageInfo<UserQueryResp> queryBinadUser(UserQueryParam userQueryParam) {
        PageHelper.startPage(userQueryParam.getPageNum(), userQueryParam.getPageSize());
        // 查询用户列表数据
        List<IamUserInfo> userInfoList = userInfoMapper.queryBindUser(userQueryParam);
        if (CollectionUtils.isEmpty(userInfoList)) {
            return new PageInfo<>();
        }
        List<UserQueryResp> userQueryResps = new ArrayList<>();
        // 循环处理，封装数据，组织名称
        userInfoList.forEach(item -> {
            UserQueryResp userQueryResp = new UserQueryResp();
            BeanUtils.copyProperties(item, userQueryResp);
            List<String> orgcodeList = Arrays.asList(item.getOrgCode().split(","));
            if (CollectionUtils.isNotEmpty(orgcodeList)) {
                // 根据组织类型+组织编码查询
                List<OrgInfoTypeVo> orgInfoVos = orgInfoService.queryByCode(orgcodeList, item.getOrgTypeCode());
                List<String> orgInfos = new ArrayList<>();
                // 封装组织数据
                if (CollectionUtils.isNotEmpty(orgInfoVos)) {
                    orgInfoVos.forEach(info -> {
                        orgInfos.add(info.getOrgTypeName() + "-" + info.getOrgName());
                    });
                    userQueryResp.setOrgInfos(orgInfos);
                }
            }
            userQueryResps.add(userQueryResp);
        });
        return new PageInfo<>(userQueryResps);
    }

    @Override
    public List<IamUserTypeExtendedField> getUserTypeExtend(String userTypeCode, String companyCode) {
        return userInfoMapper.getUserTypeExtend(userTypeCode, companyCode);
    }

    @Override
    @Transactional
    public void addUserInfo(UserInfoAddDto userInfoAddDto) {
        // 新增用户生成用户ID时加锁，失效时间10分钟
        RLock lock = redissonClient.getLock(RedisConstants.USER_INFO_CODE_LOCK);
        Long code = null;
        try {
            // 5分钟内重试获取锁，10秒后释放
            boolean isLocked = lock.tryLock(5 * 60 * 1000L, 10 * 1000L, TimeUnit.MILLISECONDS);
            // 获取到锁后，进行自增
            if (!isLocked) {
                log.warn("Route=>UserInfoServiceImpl method=>addUserInfo 新增用户加锁生成用户ID失败:{}", Json.toJsonString(userInfoAddDto));
                throw new Exception();
            }
            // 加锁成功后获取当前缓存值
            String value = RedisUtils.get(envName + RedisConstants.USER_INFO_CODE);
            // 若为空则从数据库取当前最大值，并加新增用户数量入缓存
            if (StringUtils.isEmpty(value)) {
                code = Long.valueOf(userInfoMapper.getMaxUserCode()) + 1;
            } else {
                // 当前缓存获取成功，并加新增用户数量入缓存
                code = Long.parseLong(value) + 1;
            }
            // 将最新值更新到缓存中
            RedisUtils.set(envName + RedisConstants.USER_INFO_CODE, String.valueOf(code));
        } catch (Exception e) {
            log.error("Route=>UserInfoServiceImpl method=>addUserInfo 新增用户加锁生成用户ID失败:{}, e:{}", Json.toJsonString(userInfoAddDto), e);
            throw new RuntimeException("新增用户生成用户ID异常");
        } finally {
            // 手动解锁
            if (lock.isLocked()) {
                lock.unlock();
            }
        }
        //设置用户id
        userInfoAddDto.setUserCode(String.format("%010d", code));
        //系统生成用户编码
        userInfoAddDto.setEmployeeCode(this.getEmployeeCodeByRedis("iam", 6,userInfoAddDto.getCompanyCode()));
        if (StringUtils.isNotEmpty(userInfoAddDto.getOrgCode())) {
            //判断用户组织编码后是否有","相连
            if (!",".equals(userInfoAddDto.getOrgCode().substring(userInfoAddDto.getOrgCode().length() - 1))) {
                userInfoAddDto.setOrgCode(userInfoAddDto.getOrgCode() + ",");
            }
        }
        //添加用户主数据
        userInfoMapper.addUserInfoMain(userInfoAddDto);

        //List<Map<String, String>> fieldMap = new ArrayList<>();
        //新增扩展字段数据
        if (CollectionUtils.isNotEmpty(userInfoAddDto.getExtendData())) {
            List<Map<String, String>> maps = this.extendData(userInfoAddDto);
//            for (Map<String, String> extendDatum : userInfoAddDto.getExtendData()) {
//                if (MapUtils.isNotEmpty(extendDatum)) {
//                    Set<String> keys = extendDatum.keySet();
//                    for (String fieldId : keys) {
//                        String data = extendDatum.get(fieldId);
//                        //拼接字段
//                        Map<String, String> dataMap = new HashMap<>();
//                        dataMap.put("fieldId", fieldId);//字段id
//                        dataMap.put("data", data);//字段对应的值
//                        dataMap.put("userCode", userInfoAddDto.getUserCode());//用户id
//                        dataMap.put("companyCode", userInfoAddDto.getCompanyCode());
//                        dataMap.put("createPerson", userInfoAddDto.getCreatePerson());
//                        fieldMap.add(dataMap);
//                    }
//                }
//            }
            //保存扩展字段数据
            userInfoMapper.insetExtendInfo(maps);
        }
        //  todo  添加自动生成账号的逻辑
        // 新增用户自动创建账户
        // 调用同步人资数据时生成账号功能
        List<AccountInfoDto> infoDtos = new ArrayList<>();
        AccountInfoDto accountInfoDto = new AccountInfoDto();
        accountInfoDto.setUserCode(userInfoAddDto.getUserCode());
        accountInfoDto.setName(userInfoAddDto.getName());
        accountInfoDto.setPhone(userInfoAddDto.getPhone());
        accountInfoDto.setEmail(userInfoAddDto.getEmail());
        accountInfoDto.setGender(userInfoAddDto.getGender());
        accountInfoDto.setCompanyCode(userInfoAddDto.getCompanyCode());
        accountInfoDto.setOrgTypeCode(userInfoAddDto.getOrgTypeCode());
        //设置密码为手机号后六位  加密入库
        accountInfoDto.setPassword(DigestUtils.md5DigestAsHex(userInfoAddDto.getPhone().substring(userInfoAddDto.getPhone().length() - 6).getBytes()));
        infoDtos.add(accountInfoDto);
        log.error("Route远程调用 ident => feign=>autoCreateAccount 用户中心自动创建账户接口前:{}", Json.toJsonString(infoDtos));
        Result result = identFeignInterface.autoCreateAccount(infoDtos);
        log.error("Route远程调用 ident => feign=>autoCreateAccount 用户中心自动创建账户接口后:{}", Json.toJsonString(result));
        if (!result.isSuccess()) {
            log.error("Route远程调用 ident => feign=>autoCreateAccount 用户中心自动创建账户接口失败:{}", Json.toJsonString(result));
            throw new RuntimeException("Route远程调用 ident => feign=>autoCreateAccount 用户中心自动创建账户接口失败!!!");
        }
        // 获取自动创建成功的用户ID
        if (null != result && result.getCode() != 9) {
            List<String> userCodes = (List<String>) result.getData();
            if (CollectionUtils.isNotEmpty(userCodes)) {
                // 批量更新为已开通账户
                userInfoMapper.updateByUserCode(userCodes);
            }
        }
    }

    @Override
    public PageInfo selectUserInfo(UserInfoSelectDto userInfoSelectDto) {
        userInfoSelectDto.init();
        PageHelper.startPage(userInfoSelectDto.getCurrPage(), userInfoSelectDto.getPageSize());
        //根据条件查询用户数据
        List<UserInfoSelectVo> list = this.selectUserData(userInfoSelectDto);
        PageInfo<UserInfoSelectVo> page = new PageInfo<>(list);
        PageInfo<UserInfoSelectVo> pageInfo =
                PageHelperTool.initPageInfoObj(userInfoSelectDto.getCurrPage(), (int) page.getTotal(), userInfoSelectDto.getPageSize(), page);
        return pageInfo;
    }

    @Override
    @Transactional
    public void deleteUserInfo(UserInfoDeleteDto userInfoDeleteDto, HttpServletRequest httpServletRequest) {
        //批量删除用户数据
        userInfoMapper.deleteUserInfo(userInfoDeleteDto);
        //删除扩展字段数据
        userInfoMapper.deleteUserExtended(userInfoDeleteDto);
        //清除用户和角色,用户组,的绑定关系
        Result result = applySystemFeign.deleteUserRelation(userInfoDeleteDto);
        log.info("远程调用auth服务清除用户和角色,用户组,的绑定关系{}",Json.toJsonString(result));
        if (!result.isSuccess()) {
            log.error("远程调用auth服务清除用户和角色,用户组,的绑定关系=>失败{}",Json.toJsonString(result));
            throw new RuntimeException("远程调用auth服务清除用户和角色,用户组,的绑定关系失败!!!");
        }
        //设置账号删除
        //强制登出
        Result accountResult = identFeignInterface.deleteAccount(userInfoDeleteDto);
        log.info("远程调用ident服务删除账户数据{}",Json.toJsonString(accountResult));
        if (!accountResult.isSuccess()) {
            log.error("远程调用ident服务删除账户数据=>失败{}",Json.toJsonString(accountResult));
            throw new RuntimeException("远程调用ident服务删除账户数据失败!!!");
        }
    }

    @Override
    public UserInfoVo selectUserDetail(String userCode, String companyCode) {
        //根据用户唯一标识用户id查询用户主数据
        IamUserInfo userMainData = userInfoMapper.selectUserMainData(userCode, companyCode);
        //根据唯一标识用户id查询用户扩展字段数据
        List<Map<String, String>> fieldMap = userInfoMapper.selectUserExtendedData(userCode, companyCode);
        //组装数据
        UserInfoVo userInfo = new UserInfoVo();
        BeanUtils.copyProperties(userMainData, userInfo);
        userInfo.setExtendData(fieldMap);
        return userInfo;
    }

    @Override
    @Transactional
    public void updateUserDetail(UserInfoAddDto userInfoAddDto) {
        //List<Map<String, String>> fieldMap = new ArrayList<>();
        if (StringUtils.isNotEmpty(userInfoAddDto.getOrgCode())) {
            //判断用户组织编码后是否有","相连
            if (!",".equals(userInfoAddDto.getOrgCode().substring(userInfoAddDto.getOrgCode().length() - 1))) {
                userInfoAddDto.setOrgCode(userInfoAddDto.getOrgCode() + ",");
            }
        }
        //更新用户主数据
        userInfoMapper.updateUserMainData(userInfoAddDto);
        if ("0".equals(userInfoAddDto.getOperateType())) {//"0":新增当前扩展数据
            if (CollectionUtils.isNotEmpty(userInfoAddDto.getExtendData())) {
                List<Map<String, String>> maps = this.extendData(userInfoAddDto);
//                for (Map<String, String> extendDatum : userInfoAddDto.getExtendData()) {
//                    if (MapUtils.isNotEmpty(extendDatum)) {
//                        Set<String> keys = extendDatum.keySet();
//                        for (String fieldId : keys) {
//                            String data = extendDatum.get(fieldId);
//                            //拼接字段
//                            Map<String, String> dataMap = new HashMap<>();
//                            dataMap.put("fieldId", fieldId);//字段id
//                            dataMap.put("data", data);//字段对应的值
//                            dataMap.put("userCode", userInfoAddDto.getUserCode());//用户id
//                            dataMap.put("companyCode", userInfoAddDto.getCompanyCode());
//                            dataMap.put("createPerson", userInfoAddDto.getCreatePerson());
//                            fieldMap.add(dataMap);
//                        }
//                    }
//                }
                //保存扩展字段数据
                userInfoMapper.insetExtendInfo(maps);
            }
        } else if ("1".equals(userInfoAddDto.getOperateType())) {//"1":修改原有扩展数据
            //重组扩展数据
            //List<Map<String, String>> extendData = userInfoAddDto.getExtendData();
            if (CollectionUtils.isNotEmpty(userInfoAddDto.getExtendData())) {
                List<Map<String, String>> maps = this.extendData(userInfoAddDto);
//                for (Map<String, String> map : extendData) {
//                    if (MapUtils.isNotEmpty(map)) {
//                        Set<String> keySet = map.keySet();
//                        for (String fieldId : keySet) {
//                            String data = map.get(fieldId);
//                            Map<String, String> dataMap = new HashMap<>();
//                            dataMap.put("fieldId", fieldId);
//                            dataMap.put("data", data);
//                            dataMap.put("userCode", userInfoAddDto.getUserCode());
//                            dataMap.put("companyCode", userInfoAddDto.getCompanyCode());
//                            dataMap.put("createPerson", userInfoAddDto.getCreatePerson());
//                            fieldMap.add(dataMap);
//                        }
//                    }
//                }
                //更新用户扩展字段数据
                userInfoMapper.updateUserExtendedData(maps);
            }
        } else if ("2".equals(userInfoAddDto.getOperateType())) {//"2":删除原有扩展数据,新增当前扩展数据
            //删除原有用户扩展字段数据
            //删除扩展字段数据
            UserInfoDeleteDto userInfoDeleteDto = new UserInfoDeleteDto();
            List<String> userCodes=new ArrayList<String>();
            userCodes.add(userInfoAddDto.getUserCode());
            userInfoDeleteDto.setUserCodes(userCodes);
            userInfoMapper.deleteUserExtended(userInfoDeleteDto);

            if (CollectionUtils.isNotEmpty(userInfoAddDto.getExtendData())) {
                List<Map<String, String>> maps = this.extendData(userInfoAddDto);
//                for (Map<String, String> extendDatum : userInfoAddDto.getExtendData()) {
//                    if (MapUtils.isNotEmpty(extendDatum)) {
//                        Set<String> keys = extendDatum.keySet();
//                        for (String fieldId : keys) {
//                            String data = extendDatum.get(fieldId);
//                            //拼接字段
//                            Map<String, String> dataMap = new HashMap<>();
//                            dataMap.put("fieldId", fieldId);//字段id
//                            dataMap.put("data", data);//字段对应的值
//                            dataMap.put("userCode", userInfoAddDto.getUserCode());//用户id
//                            dataMap.put("companyCode", userInfoAddDto.getCompanyCode());
//                            dataMap.put("createPerson", userInfoAddDto.getCreatePerson());
//                            fieldMap.add(dataMap);
//                        }
//                    }
//                }
                //保存扩展字段数据
                userInfoMapper.insetExtendInfo(maps);
            }
        }

    }

    /**
     * 重组用户扩展字段数据
     * @param userInfoAddDto
     * @return
     */
    private List<Map<String, String>> extendData(UserInfoAddDto userInfoAddDto) {
        List<Map<String, String>> fieldMap = new ArrayList<>();
        for (Map<String, String> extendDatum : userInfoAddDto.getExtendData()) {
            if (MapUtils.isNotEmpty(extendDatum)) {
                Set<String> keys = extendDatum.keySet();
                for (String fieldId : keys) {
                    String data = extendDatum.get(fieldId);
                    //拼接字段
                    Map<String, String> dataMap = new HashMap<>();
                    dataMap.put("fieldId", fieldId);//字段id
                    dataMap.put("data", data);//字段对应的值
                    dataMap.put("userCode", userInfoAddDto.getUserCode());//用户id
                    dataMap.put("companyCode", userInfoAddDto.getCompanyCode());
                    dataMap.put("createPerson", userInfoAddDto.getCreatePerson());
                    fieldMap.add(dataMap);
                }
            }
        }
        return fieldMap;
    }

//    @Override
//    @Transactional
//    public String userInfoImport(List<UserInfoExcelDto> userInfoExcelDtos, String companyCode, String createPerson) {
//        //导入成功的数量
//        int successNum = 0;
//        //导入失败的数量
//        int failureNum = 0;
//        //导入成功消息
//        StringBuilder successMsg = new StringBuilder();
//        //导入失败消息
//        StringBuilder failureMsg = new StringBuilder();
//        //判断导入文件数据是否为空
//        if (CollectionUtils.isEmpty(userInfoExcelDtos)) {
//            return failureMsg.append("导入文件为空!").toString();
//        }
//        //遍历文件数据,逐条校验导入
//        for (UserInfoExcelDto userInfoExcelDto : userInfoExcelDtos) {
//            try {
//                //保存添加的数据
//                UserInfoAddDto userInfoAddDto = new UserInfoAddDto();
//                //判断用户名是否为空
//                if (StringUtils.isEmpty(userInfoExcelDto.getName())) {
//                    failureNum++;
//                    failureMsg.append("<br/>" + failureNum + "、用户名为空");
//                }else {
//                    //取出组织编码,校验是否为同一组织类型下组织
//                    if (StringUtils.isNotEmpty(userInfoExcelDto.getBusinessOrgCode())) {
//                        String[] orgStr = userInfoExcelDto.getBusinessOrgCode().split(",");
//                        List<String> orgCodes = Arrays.asList(orgStr);
//                        //验证组织是否属于同一组织类型
//                        List<String> orgTypes = userInfoMapper.verifyOrgType(orgCodes);
//                        //校验组织是不是本系统组织类型下的组织
//                        if (CollectionUtils.isEmpty(orgTypes)) {
//                            failureNum++;
//                            failureMsg.append("<br/>" + failureNum + "、用户 " + userInfoExcelDto.getName() + " 用户所在组织不是本系统组织类型下的组织");
//                        } else if (orgTypes.size() != 1) {//校验组织是否隶属于多个组织类型下的组织
//                            failureNum++;
//                            failureMsg.append("<br/>" + failureNum + "、用户 " + userInfoExcelDto.getName() + " 用户所在组织隶属于多个组织类型下的组织");
//                        } else {
//                            //取出组织类型编码
//                            String orgTypeCode = orgTypes.get(0);
//                            userInfoAddDto.setOrgTypeCode(orgTypeCode);
//                            //校验手机号是否为空
//                            if (StringUtils.isEmpty(userInfoExcelDto.getPhone())) {
//                                failureNum++;
//                                failureMsg.append("<br/>" + failureNum + "、用户 " + userInfoExcelDto.getName() + " 用户手机号为空");
//                            } else {
//                                //校验同一组织类型只有一个手机号
//                                int verifyPhone = this.verifyPhone(orgTypeCode, userInfoExcelDto.getPhone());
//                                if (verifyPhone > 0) {
//                                    failureNum++;
//                                    failureMsg.append("<br/>" + failureNum + "、用户 " + userInfoExcelDto.getName() + " 用户手机号在同一组织类型下已存在");
//                                } else {
//                                    userInfoAddDto.setPhone(userInfoExcelDto.getPhone());
//                                    //生成用户唯一id
//                                    // 新增用户生成用户ID时加锁，失效时间10分钟
//                                    RLock lock = redissonClient.getLock(RedisConstants.USER_INFO_CODE_LOCK);
//                                    Long code = null;
//                                    try {
//                                        // 5分钟内重试获取锁，10秒后释放
//                                        boolean isLocked = lock.tryLock(5 * 60 * 1000L, 10 * 1000L, TimeUnit.MILLISECONDS);
//                                        // 获取到锁后，进行自增
//                                        if (!isLocked) {
//                                            log.warn("Route=>UserInfoServiceImpl method=>userInfoImport 导入用户加锁生成用户ID失败:{}", Json.toJsonString(userInfoExcelDto));
//                                            throw new Exception();
//                                        }
//                                        // 加锁成功后获取当前缓存值
//                                        String value = RedisUtils.get(RedisConstants.USER_INFO_CODE);
//                                        // 若为空则从数据库取当前最大值，并加新增用户数量入缓存
//                                        if (StringUtils.isEmpty(value)) {
//                                            code = Long.valueOf(userInfoMapper.getMaxUserCode()) + 1;
//                                        } else {
//                                            // 当前缓存获取成功，并加新增用户数量入缓存
//                                            code = Long.parseLong(value) + 1;
//                                        }
//                                        // 将最新值更新到缓存中
//                                        RedisUtils.set(RedisConstants.USER_INFO_CODE, String.valueOf(code));
//                                    } catch (Exception e) {
//                                        failureNum++;
//                                        failureMsg.append("<br/>" + failureNum + "、用户 " + userInfoExcelDto.getName() + " 导入用户加锁生成用户ID失败");
//                                        log.error("Route=>UserInfoServiceImpl method=>userInfoImport 导入用户加锁生成用户ID失败:{}, e:{}", Json.toJsonString(userInfoExcelDto), e);
//                                        throw new RuntimeException("导入用户生成用户ID异常");
//                                    } finally {
//                                        // 手动解锁
//                                        if (lock.isLocked()) {
//                                            lock.unlock();
//                                        }
//                                    }
//                                    //设置用户id
//                                    userInfoAddDto.setUserCode(String.format("%010d", code));
//                                    //设置业务系统用户ID
//                                    userInfoAddDto.setUserId(String.format("%010d", code));
//
//                                    if (StringUtils.isNotEmpty(userInfoExcelDto.getBusinessOrgCode())) {
//                                        //判断用户组织编码后是否有","相连
//                                        if (!",".equals(userInfoExcelDto.getBusinessOrgCode().substring(userInfoExcelDto.getBusinessOrgCode().length() - 1))) {
//                                            userInfoAddDto.setBusinessOrgCode(userInfoExcelDto.getBusinessOrgCode() + ",");
//                                        }
//                                    }
//                                    //设置用户状态
//                                    userInfoAddDto.setEmployeeStatus(4);
//                                    if (StringUtils.isNotEmpty(userInfoExcelDto.getEmployeeCode())) {
//                                        //校验用户编码唯一
//                                        int verifyEmployeeCode = this.verifyEmployeeCode(userInfoExcelDto.getEmployeeCode());
//                                        if (verifyEmployeeCode > 0) {
//                                            failureNum++;
//                                            failureMsg.append("<br/>" + failureNum + "、用户 " + userInfoExcelDto.getName() + " 用户编码已存在");
//                                        } else {
//                                            userInfoAddDto.setEmployeeCode(userInfoExcelDto.getEmployeeCode());
//                                            //把数据添加到数据库中
//                                            userInfoMapper.addUserInfoMain(userInfoAddDto);
//                                            successNum++;
//                                            successMsg.append("<br/>" + successNum + "、用户 " + userInfoExcelDto.getName() + " 导入成功");
//                                        }
//                                    } else {
//                                        //系统生成用户编码
//                                        userInfoAddDto.setEmployeeCode(this.getIdByRedis("iam", 6));
//                                        //把数据添加到数据库中
//                                        userInfoMapper.addUserInfoMain(userInfoAddDto);
//                                        successNum++;
//                                        successMsg.append("<br/>" + successNum + "、用户 " + userInfoExcelDto.getName() + " 导入成功");
//                                    }
//                                }
//                            }
//                        }
//                    }
//                }
//            } catch (Exception e) {
//                failureNum++;
//                String msg = "<br/>" + failureNum + "、用户数据导入失败：";
//                failureMsg.append(msg + e.getMessage());
//                log.error(msg, e);
//            }
//        }
//        if (failureNum > 0) {
//            failureMsg.insert(0, "很抱歉，导入失败！共 " + failureNum + " 条数据格式不正确，错误如下：");
//            return failureMsg.toString();
//        } else {
//            successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + successNum + " 条，数据如下：");
//        }
//        return successMsg.toString();
//    }

    @Override
    @Transactional
    public Result userInfoImport(List<UserInfoExcelDto> userInfoExcelDtos, String companyCode, String createPerson, String adminRoleCode) {
        //将要导入的数据
        List<UserInfoAddDto> importList = new ArrayList<UserInfoAddDto>();
        //远程调用生成账号
        List<AccountInfoDto> infoDtos = new ArrayList<>();
        //判断导入文件数据是否为空
        if (CollectionUtils.isEmpty(userInfoExcelDtos)) {
            return Result.failWithMsg("导入文件为空!");
        }
        try {
            //处理导入数据
            //去除重复数据  TODO  wjy  注意空数据
            //userInfoExcelDtos.stream().distinct().collect(Collectors.toList());
            //去除相同手机号的数据
            List<UserInfoExcelDto> collect = userInfoExcelDtos.stream().collect(
                    Collectors.collectingAndThen(
                            Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(UserInfoExcelDto::getPhone))), ArrayList::new)
            );
            if(collect.size() < userInfoExcelDtos.size()) {
                return Result.failWithMsg(String.format("共：%d 条'手机'数据重复，请筛选excel文件中的重复的'手机'数据后，重新导入!", userInfoExcelDtos.size() - collect.size()));
            }
            //遍历文件数据,逐条校验导入
            for (UserInfoExcelDto userInfoExcelDto : userInfoExcelDtos) {
                //保存添加的数据
                UserInfoAddDto userInfoAddDto = new UserInfoAddDto();
                //保存账号数据
                AccountInfoDto accountInfoDto = new AccountInfoDto();
                //判断用户名是否为空
                if (StringUtils.isEmpty(userInfoExcelDto.getName())) {
                    return Result.failWithMsg("用户名不能为空");
                } else {
                    String name = userInfoExcelDto.getName();
                    //添加姓名数据
                    userInfoAddDto.setName(userInfoExcelDto.getName());
                    accountInfoDto.setName(userInfoExcelDto.getName());
                    //取出组织编码,校验是否为同一组织类型下组织
                    if (StringUtils.isNotEmpty(userInfoExcelDto.getOrgCode())) {
                        String[] orgStr = userInfoExcelDto.getOrgCode().split(",");
                        List<String> orgCodes = Arrays.asList(orgStr);
                        //校验填入组织是否重复
                        List<String> orgList = orgCodes.stream().distinct().collect(Collectors.toList());
                        if (orgCodes.size() > orgList.size()) {
                            return Result.failWithMsg("用户: " + name + " 所填写的组织重复,请重新检查后再导入!!!");
                        }
                        //校验填入的组织是否存在
                        for (String orgCode : orgCodes) {
                            int count = userInfoMapper.verifyOrg(orgCode, companyCode);
                            if (count == 0) {
                                return Result.failWithMsg("用户: " + name + " 所填写的 '" + orgCode + "' 不存在,请重新检查后再导入!!!");
                            }
                        }
                        //验证组织是否属于同一组织类型
                        List<String> orgTypes = userInfoMapper.verifyOrgType(orgCodes, companyCode);
                        //校验组织是不是本系统组织类型下的组织
                        if (CollectionUtils.isEmpty(orgTypes)) {
                            return Result.failWithMsg("用户: " + name + " 所在组织不是本系统组织类型下的组织");
                        } else if (orgTypes.size() != 1) {//校验组织是否隶属于多个组织类型下的组织
                            return Result.failWithMsg("用户: " + name + " 所在组织隶属于多个组织类型下的组织");
                        } else {
                            //判断是否为数据权限下的组织类型
                            ////查询权限范围内的组织类型
                            List<String> orgTypePermission = this.getUserOrgTypePermission(adminRoleCode, companyCode);
                            //判断是否在权限范围内的组织类型
                            if (!this.includeOrg(orgTypePermission, orgTypes)) {
                                return Result.failWithMsg("用户: " + name + " 所填组织不在当前登录人的组织类型权限范围内!!!");
                            }
                            //查询权限下的组织范围
                            List<String> orgPermission = this.getUserOrgPermission(adminRoleCode, companyCode);
                            //判断是否在权限范围内的组织
                            if (!this.includeOrg(orgPermission, orgCodes)) {
                                return Result.failWithMsg("用户: " + name + " 所填组织不在当前登录人的权限范围内!!!");
                            }
                            //取出组织类型编码
                            String orgTypeCode = orgTypes.get(0);
                            userInfoAddDto.setOrgTypeCode(orgTypeCode);
                            accountInfoDto.setOrgTypeCode(orgTypeCode);
                            //校验手机号是否为空
                            if (StringUtils.isEmpty(userInfoExcelDto.getPhone())) {
                                return Result.failWithMsg("用户: " + name + " 手机号为空");
                            } else {
                                //校验同一组织类型只有一个手机号
                                int verifyPhone = this.verifyPhone(orgTypeCode, userInfoExcelDto.getPhone(), companyCode);
                                if (verifyPhone > 0) {
                                    return Result.failWithMsg("用户: " + name + " 手机号在同一组织类型下已存在");
                                } else {
                                    userInfoAddDto.setPhone(userInfoExcelDto.getPhone());
                                    accountInfoDto.setPhone(userInfoExcelDto.getPhone());
                                    //生成用户唯一id
                                    // 新增用户生成用户ID时加锁，失效时间10分钟
                                    RLock lock = redissonClient.getLock(RedisConstants.USER_INFO_CODE_LOCK);
                                    Long code = null;
                                    try {
                                        // 5分钟内重试获取锁，10秒后释放
                                        boolean isLocked = lock.tryLock(5 * 60 * 1000L, 10 * 1000L, TimeUnit.MILLISECONDS);
                                        // 获取到锁后，进行自增
                                        if (!isLocked) {
                                            log.warn("Route=>UserInfoServiceImpl method=>userInfoImport 导入用户加锁生成用户ID失败:{}", Json.toJsonString(userInfoExcelDto));
                                            throw new Exception();
                                        }
                                        // 加锁成功后获取当前缓存值
                                        String value = RedisUtils.get(envName + RedisConstants.USER_INFO_CODE);
                                        // 若为空则从数据库取当前最大值，并加新增用户数量入缓存
                                        if (StringUtils.isEmpty(value)) {
                                            code = Long.valueOf(userInfoMapper.getMaxUserCode()) + 1;
                                        } else {
                                            // 当前缓存获取成功，并加新增用户数量入缓存
                                            code = Long.parseLong(value) + 1;
                                        }
                                        // 将最新值更新到缓存中
                                        RedisUtils.set(envName + RedisConstants.USER_INFO_CODE, String.valueOf(code));
                                    } catch (Exception e) {
                                        log.error("Route=>UserInfoServiceImpl method=>userInfoImport 导入用户加锁生成用户ID失败:{}, e:{}", Json.toJsonString(userInfoExcelDto), e);
                                        throw new RuntimeException("导入用户生成用户ID异常");
                                    } finally {
                                        // 手动解锁
                                        if (lock.isLocked()) {
                                            lock.unlock();
                                        }
                                    }
                                    //设置用户id
                                    userInfoAddDto.setUserCode(String.format("%010d", code));
                                    accountInfoDto.setUserCode(String.format("%010d", code));

                                    if (StringUtils.isNotEmpty(userInfoExcelDto.getOrgCode())) {
                                        //判断用户组织编码后是否有","相连
                                        if (!",".equals(userInfoExcelDto.getOrgCode().substring(userInfoExcelDto.getOrgCode().length() - 1))) {
                                            userInfoAddDto.setOrgCode(userInfoExcelDto.getOrgCode() + ",");
                                        }
                                    }
                                    //设置用户默认状态(在职)
                                    userInfoAddDto.setEmployeeStatus(4);
                                    //系统生成用户编码
                                    userInfoAddDto.setEmployeeCode(this.getEmployeeCodeByRedis("iam", 6, companyCode));
                                    userInfoAddDto.setCompanyCode(companyCode);
                                    userInfoAddDto.setCreatePerson(createPerson);
                                    //把数据添加到数据库中
                                    importList.add(userInfoAddDto);

                                    accountInfoDto.setCompanyCode(companyCode);
                                    accountInfoDto.setCreatePerson(createPerson);
                                    //设置密码为手机号后六位  加密入库
                                    accountInfoDto.setPassword(DigestUtils.md5DigestAsHex(userInfoExcelDto.getPhone().substring(userInfoExcelDto.getPhone().length() - 6).getBytes()));
                                    //保存到账号数据list
                                    infoDtos.add(accountInfoDto);
                                }
                            }
                        }
                    } else {
                        return Result.failWithMsg("用户: " + name + " 未填写组织编码,请重新检查后再导入!!!");
                    }
                }
            }
            //批量插入用户数据
            userInfoMapper.insetUserInfoList(importList);

            // 新增用户自动创建账户
            log.error("Route远程调用 ident => feign=>autoCreateAccount 用户中心自动创建账户接口前:{}", Json.toJsonString(infoDtos));
            Result result = identFeignInterface.autoCreateAccount(infoDtos);
            log.error("Route远程调用 ident => feign=>autoCreateAccount 用户中心自动创建账户接口后:{}", Json.toJsonString(result));
            if (!result.isSuccess()) {
                log.error("批量导入用户,远程调用自动创建账户接口失败:{}", Json.toJsonString(result));
                log.error("Route远程调用 ident => feign=>autoCreateAccount 用户中心自动创建账户接口失败:{}", Json.toJsonString(result));
                throw new RuntimeException("Route批量导入用户,远程调用 ident => feign=>autoCreateAccount 用户中心自动创建账户接口失败!!!");
            }

        } catch (Exception e) {
            throw new RuntimeException("用户数据导入失败！");
        }
        return Result.successWithMsg("文件导入成功");
    }

    /**
     * 根据角色获取组织类型权限
     * @param adminRoleCode
     * @param companyCode
     * @return
     */
    private List<String> getUserOrgTypePermission(String adminRoleCode, String companyCode) {
        List<IamAdminRoleOrgInfo> adminRoleOrgInfo = adminRoleMapper.getAdminRoleOrgInfo(adminRoleCode, companyCode);
        List<String> orgTypeRole = new ArrayList<String>();
        if (CollectionUtils.isNotEmpty(adminRoleOrgInfo)) {
            String orgTypeCode = adminRoleOrgInfo.get(0).getOrgTypeCode();
            orgTypeRole.add(orgTypeCode);
        }
        return orgTypeRole;
    }

    @Override
    public List<UserInfoSelectVo> selectUserData(UserInfoSelectDto userInfoSelectDto) {
        List<UserInfoSelectVo> list = userInfoMapper.selectUserInfo(userInfoSelectDto);
        for (UserInfoSelectVo userInfoSelectVo : list) {
            String orgNameStr = "";
            if (StringUtils.isNotEmpty(userInfoSelectVo.getOrgCode())) {
                String[] orgStr = userInfoSelectVo.getOrgCode().split(",");
                List<String> orgCodes = Arrays.asList(orgStr);
                //根据组织编码获取组织名称
                List<String> orgNames = userInfoMapper.getOrgNames(orgCodes,userInfoSelectDto.getCompanyCode());
                if (CollectionUtils.isNotEmpty(orgNames)) {
                    for (String name : orgNames) {
                        orgNameStr = orgNameStr + name + ",";
                    }
                }
                //根据岗位编码获取岗位名称
                List<String> postNames = userInfoMapper.getPostNames(orgCodes,userInfoSelectDto.getCompanyCode());
                if (CollectionUtils.isNotEmpty(postNames)) {
                    for (String name : postNames) {
                        orgNameStr = orgNameStr + name + ",";
                    }
                }
            }
            userInfoSelectVo.setOrgName(orgNameStr);
        }
        return list;
    }

    /**
     * 获取用户编码(工号)
     *
     * @param prefix
     * @param numLength
     * @param companyCode
     * @return
     */
    public String getEmployeeCodeByRedis(String prefix, int numLength, String companyCode) {
        // 生成用户编码(工号)加锁，失效时间10分钟
        RLock lock = redissonClient.getLock(RedisConstants.USER_EMPLOYEE_CODE_LOCK);
        String returnCode="";
        try {
            String upperCode ="";
            //Redis中存储的key
            String key = "user_" + prefix;
            Long size = redisTemplate.opsForList().size(key);//查找 prefix 的key值的数据长度
            if (size > 0) {//有数据
                List leve = redisTemplate.opsForList().range(key, 0, -1);//获取该key下面的所有值(-1 所有的值，；1下一个值
                upperCode = leve.get(leve.size() - 1).toString();//返回最后一个值
            }
            //判断redis中序列是否为空
            if (org.apache.commons.lang3.StringUtils.isEmpty(upperCode)) {
                //获取用户编码
                upperCode = userInfoMapper.selectEmployeeCode(companyCode);
            }
            int Suffix;  //后缀数字
            if (!StringUtil.isNullOrEmpty(upperCode)) { //有数据
                String sequence = upperCode.substring(prefix.length());//截取前缀开始的后面的数字
                Suffix = Integer.parseInt(sequence);
                Suffix++;//最后的序号加一
            } else {
                Suffix = 1;//没有数据
            }
            returnCode = prefix + String.format("%0" + numLength + "d", Suffix);//后缀不够numLength长，前面补充0
            redisTemplate.opsForList().rightPush(key, returnCode);//存入Redis
        } catch (Exception e) {
            log.error("Route=>OrgTypeServiceImpl method=>getIdByRedis 生成用户编码(工号)加锁失败:", e);
            throw new RuntimeException("生成用户编码(工号)异常");
        } finally {
            // 手动解锁
            if (lock.isLocked()) {
                lock.unlock();
            }
        }
        return  returnCode;
    }

    @Override
    public int verifyEmployeeCode(String employeeCode) {
        return userInfoMapper.verifyEmployeeCode(employeeCode);
    }

    @Override
    public int verifyPhone(String orgTypeCode, String phone, String companyCode) {
        return userInfoMapper.verifyPhone(orgTypeCode, phone,companyCode);
    }

    @Override
    public List<IamUserTypeBase> getUserType(String companyCode) {
        return userInfoMapper.getUserType(companyCode);
    }

    @Override
    public IamUserTypeExtendedField getExtendInfo(String fieldId, String companyCode) {
        return userInfoMapper.getExtendInfo(fieldId, companyCode);
    }

    @Override
    public int verifyIsSole(String fieldId, String fieldData, String companyCode) {
        return userInfoMapper.verifyIsSole(fieldId, fieldData, companyCode);
    }

    @Override
    public String verifyFieldData(String fieldId, String userCode, String companyCode) {
        return userInfoMapper.verifyFieldData(fieldId, userCode, companyCode);
    }

    /**
     * 功能描述：根据 手机+组织类型编码+租户编码 查询是否存在该用户
     * @param iamUserInfoParam
     * @return IamUserInfo
     */
    @Override
    public IamUserInfo getUserInfoByAny(IamUserInfoParam iamUserInfoParam) {
        return userInfoMapper.getUserInfoByAny(iamUserInfoParam);
    }

    /**
     * 功能描述：角色关联用户查询-——查询某个角色下绑定的用户
     * @param
     */
    @Override
    public PageInfo<IamUserInfo> queryRoleBindUsers(IamRoleQueryUserParam iamRoleQueryUserParam) {
        iamRoleQueryUserParam.init();
        PageHelper.startPage(iamRoleQueryUserParam.getCurrPage(),iamRoleQueryUserParam.getPageSize());
        List<IamUserInfo> userInfos = userInfoMapper.queryRoleBindUsers(iamRoleQueryUserParam.getEmployeeCode(),
                iamRoleQueryUserParam.getName(),
                iamRoleQueryUserParam.getUserCodes());
        PageInfo<IamUserInfo> pageInfo0 = new PageInfo<>(userInfos);
        PageInfo<IamUserInfo> pageInfo = PageHelperTool.initPageInfoObj(iamRoleQueryUserParam.getCurrPage(), (int) pageInfo0.getTotal(),
                iamRoleQueryUserParam.getPageSize(), pageInfo0);
        return pageInfo;
    }

    /**
     * 功能描述：查询某个角色下还未绑定的用户
     * @param iamRoleQueryUserParam
     * @return Result
     */
    @Override
    public PageInfo<IamUserInfo> queryRoleNotBindUsers(IamRoleQueryUserParam iamRoleQueryUserParam) {
        iamRoleQueryUserParam.init();
        PageHelper.startPage(iamRoleQueryUserParam.getCurrPage(),iamRoleQueryUserParam.getPageSize());
        List<IamUserInfo> userInfos = userInfoMapper.queryRoleNotBindUsers(iamRoleQueryUserParam.getEmployeeCode(),
                iamRoleQueryUserParam.getName(),
                iamRoleQueryUserParam.getUserCodes());
        PageInfo<IamUserInfo> pageInfo0 = new PageInfo<>(userInfos);
        PageInfo<IamUserInfo> pageInfo = PageHelperTool.initPageInfoObj(iamRoleQueryUserParam.getCurrPage(), (int) pageInfo0.getTotal(),
                iamRoleQueryUserParam.getPageSize(), pageInfo0);
        return pageInfo;
    }

    @Override
    public List<String> queryOrgCode(String userCode, String companyCode){
        // 根据用户编码获取用户信息
        IamUserInfo userInfo = RedisUtils.getObject(envName + RedisConstants.IAM_USER_INFO + userCode, IamUserInfo.class);
        if (Objects.nonNull(userInfo)) {
            if (StringUtils.isEmpty(userInfo.getOrgCode())) {
                return new ArrayList<>();
            }
            return Arrays.asList(userInfo.getOrgCode().split(","));
        }
        // 缓存为空则查表
        userInfo = userInfoMapper.selectUserMainData(userCode, companyCode);
        if (Objects.isNull(userInfo)) {
            return new ArrayList<>();
        }
        // 用户信息入缓存
        RedisUtils.setObjectList(envName + RedisConstants.IAM_USER_INFO + userCode, userInfo, 60, TimeUnit.MINUTES);
        if (StringUtils.isEmpty(userInfo.getOrgCode())) {
            return new ArrayList<>();
        }
        return Arrays.asList(userInfo.getOrgCode().split(","));
    }

    @Override
    public List<String> getUserOrgPermission(String adminRoleCode, String companyCode) {
        List<IamAdminRoleOrgInfo> adminRoleOrgInfo = adminRoleMapper.getAdminRoleOrgInfo(adminRoleCode, companyCode);
        List<String> orgRole = new ArrayList<String>();
        if (CollectionUtils.isNotEmpty(adminRoleOrgInfo)) {
            if (adminRoleOrgInfo.get(0).getType() == 1) {
                //取出所有组织编码
                for (IamAdminRoleOrgInfo iamAdminRoleOrgInfo : adminRoleOrgInfo) {
                    orgRole.add(iamAdminRoleOrgInfo.getOrgCode());
                }
            } else {
                String orgTypeCode = adminRoleOrgInfo.get(0).getOrgTypeCode();
                //通过组织类型查询组织编码
                orgRole = orgInfoMapper.getOrgCodesByOrgType(orgTypeCode, companyCode);
            }
        }
        return orgRole;
    }

    @Override
    public int verifyAllNull(String userTypeCode, String companyCode) {
        return userInfoMapper.verifyAllNull(userTypeCode, companyCode);
    }

    @Override
    public String verifyUserType(UserInfoAddDto userInfoAddDto) {
        return userInfoMapper.verifyUserType(userInfoAddDto);
    }

    /**
     * 判断orgCodes是否在orgCodeList范围内
     * @param orgCodeList  大集合
     * @param orgCodes  子集合
     * @return
     */
    private boolean includeOrg(List<String> orgCodeList, List<String> orgCodes) {
        boolean anyMatch = false;
        for (String orgCode : orgCodes) {
            //判断子集合中的元素是否在大集合中
            anyMatch = orgCodeList.stream().anyMatch(f -> f.equals(orgCode));
            if (!anyMatch) {
                return anyMatch;
            }
        }
        return anyMatch;
    }


    /**
     * 功能描述：账户中心——账号列表分页条件查询（普管）
     * @param iamQueryUserByOrgParam
     * @return List
     */
    @Override
    public List<String> queryAccountListRange(IamQueryUserByOrgParam iamQueryUserByOrgParam) {
        return userInfoMapper.queryAccountListRange(iamQueryUserByOrgParam);
    }


    /**
     * 功能描述：查询动态用户组下的用户（分页展示）
     * @param：iamFilterRulesParam 筛选规则条件
     * @return PageInfo
     */
    @Override
    public PageInfo<IamUserInfo> queryDynamicUserGroupUserInfo(IamFilterRulesParam iamFilterRulesParam) {
        iamFilterRulesParam.init();
        PageHelper.startPage(iamFilterRulesParam.getCurrPage(),iamFilterRulesParam.getPageSize());
        List<IamUserGroupDynamicFilterRuleVo> filterRules = iamFilterRulesParam.getFilterRules();
        if(CollectionUtils.isEmpty(filterRules)){
            log.error("Route=>UserInfoServiceImpl method=>queryDynamicUserGroupUserInfo 该动态用户组下的筛选规则不可为空！");
            return new PageInfo<>();
        }
        filterRules.forEach(item->{
            switch (item.getRuleField()){
                case "组织部门":
                    System.out.println("星期一");
                    break;
                case "用户编码":
                    System.out.println("星期一");
                    break;
                case "姓名":
                    System.out.println("星期一");
                    break;
                case "性别":
                    System.out.println("星期一");
                    break;
                case "联系电话":
                    System.out.println("星期一");
                    break;
                case "电子邮件":
                    System.out.println("星期一");
                    break;
                case "状态":
                    System.out.println("星期一");
                    break;
                default:
                    new RuntimeException("非法请求数据");
                    break;
            }
        });

        List<IamUserInfo> iamUserInfoList = userInfoMapper.queryDynamicUserGroupUserInfo(filterRules,iamFilterRulesParam.getCompanyCode());

        return null;
    }





}
